﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.DataModel;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	public class ValveOperation
	{
		public ValveOperation(UIDocument UiDoc)
		{
			this.Doc = UiDoc.Document;
			this.Sel = UiDoc.Selection;
			this.UiDoc = UiDoc;
		}

		public bool ValveConnection(Element ele, Line line, TextNoteType textNoteType)
		{
			this.line = line;
			this.textNoteType = textNoteType;
			List<FamilyInstance> omechanicalEquipment = this.GetOMechanicalEquipment(ele);
			foreach (FamilyInstance item in omechanicalEquipment)
			{
				this.LayValue(item, ele);
			}
			if (omechanicalEquipment.Count > 0)
			{
				YJKMessageBox.Show("标注完成，未布置组合阀件的管道可能由于长度不足或已布置！");
			}
			else
			{
				YJKMessageBox.Show("标注完成，未搜到水泵或链接文件中无法布置组合阀件！");
			}
			return true;
		}

		private bool LayValue(FamilyInstance item, Element ele)
		{
			Connector connector = (from s in item.GetConnectors()
			where s.IsConnected && s.Direction == 2
			select s).FirstOrDefault<Connector>();
			this.GetFamilySymbols();
			if (connector != null)
			{
				Dictionary<string, object> faceIntersectAndPipe = this.GetFaceIntersectAndPipe((FamilyInstance)ele, connector);
				if (faceIntersectAndPipe != null && faceIntersectAndPipe.Count > 0)
				{
					if (!this.CheckPipeLength(faceIntersectAndPipe))
					{
						return false;
					}
					GroupValueManage groupValueManage = new GroupValueManage(this.Doc, (Pipe)faceIntersectAndPipe["pipe"], (XYZ)faceIntersectAndPipe["xyz"], (XYZ)faceIntersectAndPipe["xyz"], 100.0, this.fsLexibleRubberHead);
					if (((Pipe)faceIntersectAndPipe["pipe"]).Document.IsLinked)
					{
						groupValueManage.Go(this.Doc, (XYZ)faceIntersectAndPipe["xyz"], this.line, this.textNoteType, true);
					}
					else
					{
						groupValueManage.isShowMessage = false;
						Pipe pipe = groupValueManage.GetPipe(this.Doc, (XYZ)faceIntersectAndPipe["xyz"], this.line, this.textNoteType);
						if (pipe == null)
						{
							return false;
						}
						Level referenceLevel = pipe.ReferenceLevel;
						XYZ splitPoint = this.GetSplitPoint(pipe);
						double pipeDia = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).AsDouble();
						Pipe riserPipe;
						List<Pipe> pipes;
						this.CreatePipeAndConnected(pipe, splitPoint, referenceLevel, pipeDia, out riserPipe, out pipes);
						groupValueManage = new GroupValueManage(this.Doc, this.GetLayPipe(pipes), splitPoint, splitPoint, 300.0, this.fsCheckValveAndGataValve);
						groupValueManage.Go();
						this.CreatePreesureGuage(this.pressureGaugeFamilySymbol, splitPoint, referenceLevel, pipeDia, riserPipe);
					}
				}
			}
			return true;
		}

		private bool CheckPipeLength(Dictionary<string, object> intcAndPipe)
		{
			Pipe pipe = intcAndPipe["pipe"] as Pipe;
			XYZ xyz = intcAndPipe["xyz"] as XYZ;
			return (((pipe.Location as LocationCurve).Curve.GetEndPoint(0).Z > (pipe.Location as LocationCurve).Curve.GetEndPoint(1).Z) ? (pipe.Location as LocationCurve).Curve.GetEndPoint(0) : (pipe.Location as LocationCurve).Curve.GetEndPoint(1)).DistanceTo(xyz) > 4.9212598425196852;
		}

		private void GetFamilySymbols()
		{
			SpaceFamilyDataReader spaceFamilyDataReader = new SpaceFamilyDataReader();
			FamilySymbol familySymbolByNameSubTran = spaceFamilyDataReader.GetFamilySymbolByNameSubTran("可曲挠橡胶头", "PipeValve", this.Doc, BuiltInCategory.OST_PipeAccessory);
			FamilySymbol familySymbolByNameSubTran2 = spaceFamilyDataReader.GetFamilySymbolByNameSubTran("止回阀", "PipeValve", this.Doc, BuiltInCategory.OST_PipeAccessory);
			FamilySymbol familySymbolByNameSubTran3 = spaceFamilyDataReader.GetFamilySymbolByNameSubTran("闸阀", "PipeValve", this.Doc, BuiltInCategory.OST_PipeAccessory);
			this.pressureGaugeFamilySymbol = spaceFamilyDataReader.GetFamilySymbolByNameSubTran("压力表", "Accessory", this.Doc, BuiltInCategory.OST_PipeAccessory);
			this.fsLexibleRubberHead = new List<FamilySymbol>();
			this.fsLexibleRubberHead.Add(familySymbolByNameSubTran);
			this.fsCheckValveAndGataValve = new List<FamilySymbol>();
			this.fsCheckValveAndGataValve.Add(familySymbolByNameSubTran2);
			this.fsCheckValveAndGataValve.Add(familySymbolByNameSubTran3);
		}

		private void CreatePipeAndConnected(Pipe pipe, XYZ perdal, Level level, double pipeDia, out Pipe riserPipe, out List<Pipe> pipes)
		{
			Pipe pipe2 = Pipe.Create(this.Doc, this.GetPipingSystemType(pipe).Id, this.GetPipeType(pipe).Id, level.Id, perdal, perdal + this.Doc.ActiveView.RightDirection);
			pipe2.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(pipeDia);
			riserPipe = Pipe.Create(this.Doc, this.GetPipingSystemType(pipe).Id, this.GetPipeType(pipe).Id, level.Id, perdal + this.Doc.ActiveView.RightDirection, perdal + this.Doc.ActiveView.RightDirection + this.Doc.ActiveView.UpDirection);
			riserPipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM).Set(pipeDia);
			YJKPiping<Pipe> hypiping = new YJKPiping<Pipe>(pipe);
			pipes = hypiping.Separate(perdal);
			new YJKPipeConnectorHelper();
			this.Doc.Create.NewTeeFitting(this.GetCloserConnector(pipes.ElementAt(0), perdal), this.GetCloserConnector(pipes.ElementAt(1), perdal), this.GetCloserConnector(pipe2, perdal));
			this.Doc.Create.NewElbowFitting(this.GetCloserConnector(pipe2, perdal + this.Doc.ActiveView.RightDirection), this.GetCloserConnector(riserPipe, perdal + this.Doc.ActiveView.RightDirection));
		}

		private void CreatePreesureGuage(FamilySymbol pressureGaugeFamilySymbol, XYZ perdal, Level level, double pipeDia, Pipe riserPipe)
		{
			pressureGaugeFamilySymbol.Activate();
			XYZ riserPipeUpPoint = this.GetRiserPipeUpPoint(riserPipe);
			if (riserPipeUpPoint == null)
			{
				return;
			}
			FamilyInstance familyInstance = this.Doc.Create.NewFamilyInstance(riserPipeUpPoint, pressureGaugeFamilySymbol, (Autodesk.Revit.DB.Structure.StructuralType)0);
			Parameter parameter = familyInstance.GetParameters("入口直径").FirstOrDefault<Parameter>();
			if (parameter != null && !parameter.IsReadOnly)
			{
				parameter.Set(pipeDia);
			}
			Line line = Line.CreateUnbound(riserPipeUpPoint, XYZ.BasisZ);
			ElementTransformUtils.RotateElement(this.Doc, familyInstance.Id, line, this.Doc.ActiveView.ViewDirection.AngleTo(familyInstance.FacingOrientation));
			this.Doc.Regenerate();
			this.ConnectPipeAndFamilyInstance(riserPipe, familyInstance, riserPipeUpPoint);
		}

		private XYZ GetRiserPipeUpPoint(Pipe riserPipe)
		{
			XYZ result = null;
			LocationCurve locationCurve = riserPipe.Location as LocationCurve;
			if (locationCurve != null)
			{
				XYZ endPoint = locationCurve.Curve.GetEndPoint(0);
				XYZ endPoint2 = locationCurve.Curve.GetEndPoint(1);
				result = ((endPoint.Z >= endPoint2.Z) ? endPoint : endPoint2);
			}
			return result;
		}

		private XYZ GetSplitPoint(Pipe pipe)
		{
			XYZ xyz = ((pipe.Location as LocationCurve).Curve.GetEndPoint(0).Z > (pipe.Location as LocationCurve).Curve.GetEndPoint(1).Z) ? (pipe.Location as LocationCurve).Curve.GetEndPoint(1) : (pipe.Location as LocationCurve).Curve.GetEndPoint(0);
			XYZ direction = ((pipe.Location as LocationCurve).Curve as Line).Direction;
			XYZ xyz2 = (direction.Z > 0.0) ? (xyz + direction * 0.98425196850393692) : (xyz - direction * 0.98425196850393692);
			return ((pipe.Location as LocationCurve).Curve as Line).Project(xyz2).XYZPoint;
		}

		private Dictionary<string, object> GetFaceIntersectAndPipe(FamilyInstance item, Connector conn)
		{
			new Dictionary<string, object>();
			Pipe connectPipe = this.GetConnectPipe((from s in conn.AllRefs.AsEnumerable()
			where s.Owner is Pipe
			select s).FirstOrDefault<Connector>());
			SearchBranch searchBranch = new SearchBranch(this.UiDoc);
			searchBranch.DoSearch(new ElementNode(connectPipe, new YJKPiping<Pipe>(connectPipe).GetNearConnectorToPoint(conn.Origin)));
			ElementNode listRoot = searchBranch.GetListRoot();
			return this.GetFacePipeDic(item, listRoot);
		}

		private Dictionary<string, object> GetFacePipeDic(FamilyInstance item, ElementNode node)
		{
			if (node == null)
			{
				return null;
			}
			if (!(node.Element is Pipe))
			{
				return this.GetFacePipeDic(item, node.Next);
			}
			Dictionary<string, object> dictionary = new Dictionary<string, object>();
			Pipe pipe = (Pipe)node.Element;
			double elevation = (this.Doc.GetElement(item.LevelId) as Level).Elevation;
			double num = item.GetParameter("偏移量").AsDouble() + elevation;
			double num2 = pipe.GetParameter("开始偏移").AsDouble() + pipe.ReferenceLevel.GetParameter("立面").AsDouble();
			double num3 = pipe.GetParameter("端点偏移").AsDouble() + pipe.ReferenceLevel.GetParameter("立面").AsDouble();
			if (num2 > num3)
			{
				num3 = pipe.GetParameter("开始偏移").AsDouble() + pipe.ReferenceLevel.GetParameter("立面").AsDouble();
				num2 = pipe.GetParameter("端点偏移").AsDouble() + pipe.ReferenceLevel.GetParameter("立面").AsDouble();
			}
			if (num >= num2 && num <= num3)
			{
				if (YJKRevitTools.isRiserPipe(pipe))
				{
					dictionary["xyz"] = new XYZ(((LocationCurve)pipe.Location).Curve.GetEndPoint(0).X, ((LocationCurve)pipe.Location).Curve.GetEndPoint(0).Y, num);
				}
				else
				{
					XYZ xyz = new XYZ(((LocationCurve)pipe.Location).Curve.GetEndPoint(0).X, ((LocationCurve)pipe.Location).Curve.GetEndPoint(0).Y, num);
					XYZ xyz2 = new XYZ(((LocationCurve)pipe.Location).Curve.GetEndPoint(1).X, ((LocationCurve)pipe.Location).Curve.GetEndPoint(1).Y, num);
					Line line = Line.CreateBound(xyz, xyz2);
					IntersectionResultArray intersectionResultArray;
					if (((LocationCurve)pipe.Location).Curve.Intersect(line, out intersectionResultArray) != 4)
					{
						dictionary["xyz"] = intersectionResultArray.get_Item(0).XYZPoint;
					}
				}
				dictionary["pipe"] = pipe;
				return dictionary;
			}
			return this.GetFacePipeDic(item, node.Next);
		}

		private Pipe GetConnectPipe(Connector nextConn)
		{
			Pipe result = null;
			if (nextConn == null)
			{
				return result;
			}
			if (nextConn.Owner is Pipe)
			{
				result = (Pipe)nextConn.Owner;
			}
			else if (nextConn.Owner is PipingSystem)
			{
				foreach (object obj in ((PipingSystem)nextConn.Owner).Elements)
				{
					Element element = (Element)obj;
					if (element is Pipe)
					{
						result = (Pipe)element;
					}
				}
			}
			return result;
		}

		private List<FamilyInstance> GetOMechanicalEquipment(Element ele)
		{
			BoundingBoxIntersectsFilter boundingBoxIntersectsFilter = new BoundingBoxIntersectsFilter(new Outline(ele.get_BoundingBox(this.Doc.ActiveView).Min, ele.get_BoundingBox(this.Doc.ActiveView).Max));
			FilteredElementCollector filteredElementCollector;
			if (ele.Document.IsLinked)
			{
				filteredElementCollector = new FilteredElementCollector(ele.Document);
			}
			else
			{
				filteredElementCollector = new FilteredElementCollector(this.Doc);
			}
			return (from s in filteredElementCollector.WherePasses(boundingBoxIntersectsFilter).ToElements()
			where s.Category.Id.IntegerValue == -2001140
			select s).Cast<FamilyInstance>().ToList<FamilyInstance>();
		}

		private PipingSystemType GetPipingSystemType(Pipe pipe)
		{
			string pipingSystemTypeName = pipe.get_Parameter(BuiltInParameter.RBS_PIPING_SYSTEM_TYPE_PARAM).AsValueString();
			return new FilteredElementCollector(this.Doc).OfClass(typeof(PipingSystemType)).ToList<Element>().FirstOrDefault((Element p) => p.Name == pipingSystemTypeName) as PipingSystemType;
		}

		private PipeType GetPipeType(Pipe pipe)
		{
			string text = pipe.get_Parameter(BuiltInParameter.ELEM_FAMILY_AND_TYPE_PARAM).AsValueString();
			List<Element> source = new FilteredElementCollector(this.Doc).OfClass(typeof(PipeType)).ToList<Element>();
			char[] separator = new char[]
			{
				':'
			};
			string[] pipTypeName = text.Split(separator, StringSplitOptions.RemoveEmptyEntries);
			return source.FirstOrDefault((Element p) => p.Name == pipTypeName.ElementAt(1).Trim()) as PipeType;
		}

		private Connector GetCloserConnector(Pipe pipe, XYZ xyz)
		{
			return new YJKPiping<Pipe>(pipe).GetCloseConnector(xyz, false);
		}

		private Pipe GetLayPipe(List<Pipe> pipes)
		{
			if ((pipes.ElementAt(0).Location as LocationCurve).Curve.GetEndPoint(0).Z < (pipes.ElementAt(1).Location as LocationCurve).Curve.GetEndPoint(0).Z)
			{
				return pipes.ElementAt(1);
			}
			return pipes.ElementAt(0);
		}

		private void ConnectPipeAndFamilyInstance(Pipe pipe, FamilyInstance fi, XYZ point)
		{
			Connector closerConnector = this.GetCloserConnector(pipe, point);
			ConnectorSetIterator connectorSetIterator = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector = obj as Connector;
				if (!connector.IsConnected)
				{
					closerConnector.ConnectTo(connector);
				}
			}
		}

		private Document Doc;

		private Selection Sel;

		private UIDocument UiDoc;

		private Line line;

		private TextNoteType textNoteType;

		private List<FamilySymbol> fsLexibleRubberHead = new List<FamilySymbol>();

		private List<FamilySymbol> fsCheckValveAndGataValve = new List<FamilySymbol>();

		private FamilySymbol pressureGaugeFamilySymbol;
	}
}
